#include "base_tests.h"

using namespace testing;
using namespace std;
using namespace mili;
using namespace feca;

struct SlidingWindowCacheTest: public ::testing::Test
{
    vector<Foo> v;
    SlidingWindowCacheTest()
    {
        for (unsigned int i = 0; i < 100; i++)
        {
            insert_into(v, Foo(i));
        }
    }
};

template<class Cache>
static void checkDefaultCacheIntegrity(vector<Foo>& v, unsigned int window_size)
{
    Cache cache(new DefaultVectorLoader<Foo>(v));
    Foo* foo;
    for (unsigned int i = 0; i < v.size(); ++i)
    {
        foo = cache.get(i);
        ASSERT_EQ(i, foo->n);
        ASSERT_TRUE(cache.size() <= window_size);
    }
}

TEST_F(SlidingWindowCacheTest, Single)
{
    typedef SlidingWindowCache<10, DefaultVectorLoader<Foo> >::Type Cache;
    checkDefaultCacheIntegrity<Cache>(v, 10);
}

TEST_F(SlidingWindowCacheTest, Combination1)
{
    typedef SlidingWindowCache<10, SlidingWindowCache<20, DefaultVectorLoader<Foo> >::Type >::Type Cache;
    checkDefaultCacheIntegrity<Cache>(v, 10);
}

TEST_F(SlidingWindowCacheTest, Combination2)
{
    typedef SlidingWindowCache<10, SlidingWindowCache<2, DefaultVectorLoader<Foo> >::Type >::Type Cache;
    checkDefaultCacheIntegrity<Cache>(v, 10);
}

TEST_F(SlidingWindowCacheTest, Combination3)
{
    typedef SlidingWindowCache<10, SlidingWindowCache<2, SlidingWindowCache<12, DefaultVectorLoader<Foo> >::Type>::Type>::Type Cache;
    checkDefaultCacheIntegrity<Cache>(v, 10);
}
